package com.zycfc.zsf.boot.mq.rabbitmq.retry;

import java.util.concurrent.*;
import org.springframework.amqp.core.*;
import java.util.*;

public class RetryCache
{
    private final Map<String, MessageCache> messageLocalCache;
    private final RetryCacheProperties retryCacheProperties;
    
    public RetryCache(final RetryCacheProperties retryCacheProperties) {
        this.retryCacheProperties = retryCacheProperties;
        this.messageLocalCache = new ConcurrentHashMap<String, MessageCache>(retryCacheProperties.getMaxCapacity());
    }
    
    public MessageCache add(final String id, final String exchangeName, final String routingKey, final Message message) {
        if (null == id || message == null) {
            return null;
        }
        final boolean isExclude = this.isExcludeExchange(exchangeName);
        if (isExclude) {
            return null;
        }
        if (this.messageLocalCache.size() >= this.retryCacheProperties.getMaxCapacity()) {
            throw new RuntimeException("The count of unack message is over stock, " + this.retryCacheProperties.getMaxCapacity());
        }
        final MessageCache messageCache = new MessageCache();
        messageCache.setId(id);
        messageCache.setExchangeName(exchangeName);
        messageCache.setRoutingKey(routingKey);
        messageCache.setMessage(message);
        messageCache.setFirstSendTime(System.currentTimeMillis());
        messageCache.setLastSendTime(System.currentTimeMillis());
        messageCache.setSended(false);
        this.messageLocalCache.put(id, messageCache);
        return messageCache;
    }
    
    public MessageCache get(final String id) {
        if (null == id) {
            return null;
        }
        return this.messageLocalCache.get(id);
    }
    
    public void del(final String id) {
        if (null == id) {
            return;
        }
        this.messageLocalCache.remove(id);
    }
    
    public void del(final MessageCache messageCache) {
        if (null == messageCache || null == messageCache.getId()) {
            return;
        }
        this.messageLocalCache.remove(messageCache.getId());
    }
    
    public void putAll(final Map<String, MessageCache> m) {
        if (null == m || m.isEmpty()) {
            return;
        }
        this.messageLocalCache.putAll(m);
    }
    
    private boolean isExcludeExchange(final String exchangeName) {
        if (null == this.retryCacheProperties.getExcludeExchangeNames()) {
            return false;
        }
        if (null == exchangeName || exchangeName.length() == 0) {
            return true;
        }
        for (final String exchange : this.retryCacheProperties.getExcludeExchangeNames()) {
            if (exchangeName.equals(exchange)) {
                return true;
            }
        }
        return false;
    }
    
    public Map<String, MessageCache> getMessageLocalCache() {
        return this.messageLocalCache;
    }
    
    public RetryCacheProperties getRetryCacheProperties() {
        return this.retryCacheProperties;
    }
}
